/*************************************************************/
//2014.03.06修改版
/*************************************************************/
#include "fm175xx.h"
#include "type_a.h"
#include "main.h"
#include "format.h"

//ATQA只有两个字节
//UID却是4个字节加一个BCC校验值所以针对7字节UID防碰撞时就需要最多15字节的UID来存放
//SAK是一个字节的SAK+CRC_A(2字节)
u8 picc_atqa[2],picc_uid[15],picc_sak[3];
u8 CardA_Active, CardA_Rescan;

/***************************************************************************************
名称： 	TypeA_Request																	
功能： 	TypeA_Request卡片寻卡															
输入：																				     			    			     													       								 												
输出：	pTagType[0],pTagType[1] =ATQA                                         						
       	1: 应答正确                                                              	
	 		0: 应答错误																
****************************************************************************************/
u8 TypeA_Request(u8 *pTagType)
{
	u8 result,send_buff[1],rece_buff[2];
	u32  rece_bitlen;  
	
	Clear_BitMask(TxModeReg,0x80);		//关闭TX CRC
	Clear_BitMask(RxModeReg,0x80);		//关闭RX CRC
	Set_BitMask(RxModeReg, 0x08);		//关闭位接收
	Clear_BitMask(Status2Reg,0x08);
	FM175xx_Write_Register(BitFramingReg,0x07);
	send_buff[0] = 0x26;
   	FM175xx_SetTimer(1);
	Clear_FIFO();
	result = FM175xx_Comm(Transceive,send_buff,1,rece_buff,&rece_bitlen);
	if(result == 1)
	{    
		if(rece_bitlen == 2 * 8)
		{
			*pTagType     = rece_buff[0];
			*(pTagType+1) = rece_buff[1];
		}
		else
		{
			result = 0;
		}
	}
#if DEBUG > 2
	printf("==TypeA_Request(%d)=(%d)%02X%02X.\r\n", result, rece_bitlen, rece_buff[0], rece_buff[1]);
#endif
	return result;
}
/****************************************************************************************
名称： 	TypeA_WakeUp																	
功能： 	TypeA_WakeUp卡片寻卡															
输入：																				      			    			     									       								 												
输出：	pTagType[0],pTagType[1] =ATQA                                         							
       	1: 应答正确                                                              	
	 	0: 应答错误																
****************************************************************************************/
u8 TypeA_WakeUp(u8 *pTagType)
{
	u8   result,send_buff[1],rece_buff[2];
	u32   rece_bitlen;  
	
	Clear_BitMask(TxModeReg,0x80);		//关闭TX CRC
	Clear_BitMask(RxModeReg,0x80);		//关闭RX CRC
	Set_BitMask(RxModeReg, 0x08);		//不接收小于4bit的数据
	Clear_BitMask(Status2Reg,0x08);
	FM175xx_Write_Register(BitFramingReg,0x07);
 	send_buff[0] = 0x52;
   	FM175xx_SetTimer(1);
	Clear_FIFO();
	result = FM175xx_Comm(Transceive,send_buff,1,rece_buff,&rece_bitlen);

	if(result == 1)
	{    
		if(rece_bitlen == 2 * 8)
		{
			*pTagType     = rece_buff[0];
			*(pTagType+1) = rece_buff[1];
		}
		else
		{
			result = 0;
		}
	}
#if DEBUG > 2
	printf("==TypeA_WakeUp(%d)=%02X%02X.\r\n", result, rece_buff[0], rece_buff[1]);
#endif
	return result;
}
/****************************************************************************************
名称：TypeA_Anticollision																
功能：TypeA_Anticollision卡片防冲突													
输入：selcode = 0x93，0x95，0x97														      			    			     													       								 												
输出：	pSnr[0],pSnr[1],pSnr[2],pSnr[3]pSnr[4] =UID                            							
       	1: 应答正确                                                              	
	 	0: 应答错误																
****************************************************************************************/
u8 TypeA_Anticollision(u8 selcode,u8 *pSnr)
{
	u8   result,i,send_buff[2],rece_buff[5];
	u32 rece_bitlen;
	
	Clear_BitMask(TxModeReg,0x80);
	Clear_BitMask(RxModeReg,0x80);
	Clear_BitMask(Status2Reg,0x08);
	FM175xx_Write_Register(BitFramingReg,0x00);
	Clear_BitMask(CollReg,0x80);
 
	send_buff[0] = selcode;
	send_buff[1] = 0x20;             //NVB
	FM175xx_SetTimer(1);
	Clear_FIFO();
	result = FM175xx_Comm(Transceive,send_buff,2,rece_buff,&rece_bitlen);

	if (result == 1)
	{
		if(rece_bitlen == 40)
		{
			for (i=0; i<5; i++)
			{   
				*(pSnr+i)  = rece_buff[i];
			}
			if (pSnr[4] != (pSnr[0]^pSnr[1]^pSnr[2]^pSnr[3]))     //UID0、UID1、UID2、UID3、BCC(校验字节)
			{
				result = 0; 
			}
		}
		else
		{
			result = 0; 
		}
	}
#if DEBUG > 2
	printf("==TypeA_Antic(%d)=(%d)%02X%02X%02X%02X%02X.\r\n", result, rece_bitlen, rece_buff[0], rece_buff[1], rece_buff[2], rece_buff[3], rece_buff[4]);
#endif
	return result;
}
/****************************************************************************************
名称： 	TypeA_Select																	
功能： 	TypeA_Select卡片选卡															
输入：	selcode =0x93，0x95，0x97														
      	pSnr[0],pSnr[1],pSnr[2],pSnr[3]pSnr[4] =UID 			    			     	       								 												
输出：  pSak[0],pSak[1],pSak[2] =SAK			                            							
      	1: 应答正确                                                              	
		0: 应答错误																
****************************************************************************************/
u8 TypeA_Select(u8 selcode,u8 *pSnr,u8 *pSak)
{
	u8 result,i,send_buff[7],rece_buff[5];
	u32 rece_bitlen;
	
	FM175xx_Write_Register(BitFramingReg,0x00);
	Set_BitMask(TxModeReg,0x80);      //打开TX CRC
	Set_BitMask(RxModeReg,0x80);        //打开接收RX 的CRC校验
	Clear_BitMask(Status2Reg,0x08);
	
	send_buff[0] = selcode;        //SEL
	send_buff[1] = 0x70;         //NVB
    
	for (i=0; i<5; i++)
	{
		send_buff[i+2] = *(pSnr+i);
	}
   	
	FM175xx_SetTimer(1);
	Clear_FIFO();
	result = FM175xx_Comm(Transceive,send_buff,7,rece_buff,&rece_bitlen);
    
	if (result == 1)
	{ 
		if(rece_bitlen == 8)
		{
			*pSak = rece_buff[0]; 		//0x20 = CPU, 0x08 = M1, 0x28 = M1&CPU
		}
		else
		{
			result = 0;
		}
	}
#if DEBUG > 2
	printf("==TypeA_Select(%d)=(%d)%02X.\r\n", result, rece_bitlen, rece_buff[0]);
#endif
	return result;
}
/***************************************************************************************
名称： 	TypeA_Halt																		
功能： 	TypeA_Halt卡片停止																
输入：																			      			    			     											       								 												
输出：	1: 应答正确                                                              	
	 	0: 应答错误																
****************************************************************************************/
u8 TypeA_Halt(void)
{
	u8   result,send_buff[2],rece_buff[1];
	u32  rece_bitlen;
	
	send_buff[0] = 0x50;
	send_buff[1] = 0x00;
	FM175xx_Write_Register(BitFramingReg,0x00);
	Set_BitMask(TxModeReg,0x80);
	Set_BitMask(RxModeReg,0x80);
	Clear_BitMask(Status2Reg,0x08);
	FM175xx_SetTimer(1);
	Clear_FIFO();
	result = FM175xx_Comm(Transmit,send_buff,2,rece_buff,&rece_bitlen);
	return result;
}
/****************************************************************************************
名称：TypeA_CardActive																
功能：TypeA_CardActive卡片激活														
输入：																				      			    			     													       								 												
输出：	pTagType[0],pTagType[1] =ATQA 											 	
	    pSnr[0],pSnr[1],pSnr[2],pSnr[3]pSnr[4] =UID 		                   		
	    pSak[0],pSak[1],pSak[2] =SAK			                            							
       	1: 应答正确                                                              	
	 	0: 应答错误																
****************************************************************************************/
u8 TypeA_CardActive(u8 *pTagType,u8 *pSnr,u8 *pSak)
{
	u8 tmp;
	
	FM175xx_SoftReset();	
	FM175xx_Set_Rf(OPEN_ALL_TX);
	FM175xx_ConfigISOType(ISO_Cfg_TYPE_A);
	delay_ms(5);
	
	tmp = TypeA_Request(pTagType);
	if(tmp == 0xEE)				//寻卡 Standard	 send request command Standard mode	
	{
		if(CardA_Rescan >= 2)
			CardA_Active = 0;
		else
			CardA_Rescan++;
		return 0;
	}
	else if(tmp != 1)
	{
		return 0;
	}
	CardA_Rescan = 0;
	if(CardA_Active == 1)
	{
		return 2;
	}

	switch ((pTagType[0]&0xC0))        			//M1卡,ID号只有4位
	{
		case 0x00:
			{
				if(TypeA_Anticollision(0x93,pSnr) != 1)
					return 0;		

				if(TypeA_Select(0x93,pSnr,pSak) != 1)
					return 0;				
			}
			break;
		case 0x40:
			{
				if(TypeA_Anticollision(0x93,pSnr) != 1)
					return 0;

				if(TypeA_Select(0x93,pSnr,pSak) != 1)
					return 0;

				if(TypeA_Anticollision(0x95,pSnr+5) != 1)
					return 0;

				if(TypeA_Select(0x95,pSnr+5,pSak+1) != 1)
					return 0;
			}
			break;
		case 0x80:
			{
				if(TypeA_Anticollision(0x93,pSnr) != 1)
					return 0;

				if(TypeA_Select(0x93,pSnr,pSak) != 1)
					return 0;

				if(TypeA_Anticollision(0x95,pSnr+5) != 1)
					return 0;

				if(TypeA_Select(0x95,pSnr+5,pSak+1) != 1)
					return 0;

				if(TypeA_Anticollision(0x97,pSnr+10) != 1)
					return 0;

				if(TypeA_Select(0x97,pSnr+10,pSak+2) != 1)
					return 0;
			}
			break;
		default:
			break;
	}
	
	CardA_Active = 1;
	return 1;
}
/****************************************************************************************
名称：ReadCard_TypeBActive																
功能：ReadCard_TypeBActive卡片激活														
输入：																				      			    			     													       								 												
输出：															
****************************************************************************************/
u8 ReadCard_TypeAActive(u8 *csn,u8 *csn_len)
{
	u8 i;
	
	if(TypeA_CardActive(picc_atqa,picc_uid,picc_sak) == 1)
	{
		#if DEBUG > 0
			printf("A_active=(%02X%02X,%02X%02X%02X).\r\n", picc_atqa[0], picc_atqa[1], picc_sak[0], picc_sak[1], picc_sak[2]);
		#endif
		//TypeA_Halt();
		if((picc_atqa[0]&0xC0)==0x40)
		{
			*csn_len = 7;
			memcpy(csn, picc_uid+1, 3);
			memcpy(csn+3, picc_uid+5, 4);
		}
		else if((picc_atqa[0]&0xC0)==0x80)
		{
			*csn_len = 10;
			memcpy(csn, picc_uid+1, 3);
			memcpy(csn+3, picc_uid+6, 3);
			memcpy(csn+6, picc_uid+10, 4);
		}
		else //0x00
		{
			*csn_len = 4;
			memcpy(csn, picc_uid, 4);
		}
		#if DEBUG > 0
			printf("A_csn=%d: ", *csn_len);
			for(i=0;i<*csn_len;i++)
				printf("%02X", csn[i]);
			printf("\r\n");
		#endif
		return 1;
	}
	return 0;
}
